package com.alex.asynchronousorchestration.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

@RestController
@RequestMapping("/product")
public class Alex008AsynController {
    /**
     * 模拟商品服务
     */
    private String getProductInfo() {
        try {
            Thread.sleep(300);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "iphone 15";
    }

    /**
     * 模拟库存服务
     */
    private Integer getStockInfo() {
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return 10;
    }

    /**
     * 根据库存情况判断是否热销
     */
    private String checkHotSale(Integer stock) {
        return stock < 50 ? "热销商品" : "普通商品";
    }

    /**
     * 模拟促销服务
     */
    private String getPromotionInfo() {
        try {
            Thread.sleep(200);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "满1000减200";
    }

    /**
     * 同步调用
     */
    @GetMapping("/detail/sync")
    public String getproductDetailSync() {
        long start = System.currentTimeMillis();

        //同步调用
        String product = getProductInfo();
        Integer stock = getStockInfo();
        String promotion = getPromotionInfo();

        String result = String.format("商品详情页:商品:%s, 库存:%d, 促销:%s", product, stock, promotion);

        long end = System.currentTimeMillis();

        return result+ "耗时" + (end - start) + "ms";
    }

    /**
     * 异步调用
     */
    @GetMapping("detail/async")
    public String getproductDetailAsync() throws ExecutionException, InterruptedException {

        long start = System.currentTimeMillis();

        //异步调用
        CompletableFuture<String> productFuture =
                CompletableFuture.supplyAsync(() -> getProductInfo());

        CompletableFuture<Integer> stockFuture =
                CompletableFuture.supplyAsync(() -> getStockInfo());

        CompletableFuture<String> promotionFuture =
                CompletableFuture.supplyAsync(() -> getPromotionInfo());

        CompletableFuture.allOf(productFuture, stockFuture, promotionFuture)
                .join();

        String result = String.format("商品详情页:商品:%s, 库存:%d, 促销:%s",
                productFuture.get(),
                stockFuture.get(),
                promotionFuture.get()
        );

        long end = System.currentTimeMillis();

        return result + "耗时:" + (end - start) + "ms";


    }

    /**
     * then-apply   任务A完成后执行任务B,把A的结果传给B
     */
    @GetMapping("detail/then-apply")
    public String getProductDetailWithThenApply() throws ExecutionException, InterruptedException {
        CompletableFuture<String> stockFuture = CompletableFuture.supplyAsync(() -> getStockInfo())
                .thenApply(stock -> {
                    String hotSale = checkHotSale(stock);
                    return String.format("库存:%d (%s)", stock, hotSale);
                });
        return stockFuture.get();
    }

}
